<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/base/color_scheme.html">
<link rel="import" href="/tracing/base/math/statistics.html">
<link rel="import" href="/tracing/model/event.html">
<link rel="import" href="/tracing/model/event_set.html">

<script>
'use strict';

/**
 * @fileoverview Class describing rendered frames.
 *
 * Because a frame is produced by multiple threads, it does not inherit from
 * TimedEvent, and has no duration.
 */
tr.exportTo('tr.model', function() {
  const ColorScheme = tr.b.ColorScheme;
  const Statistics = tr.b.math.Statistics;

  const FRAME_PERF_CLASS = {
    GOOD: 'good',
    BAD: 'bad',
    TERRIBLE: 'terrible',
    NEUTRAL: 'generic_work'
  };

  /**
   * @constructor
   * @param {Array} associatedEvents Selection of events composing the frame.
   * @param {Array} threadTimeRanges Array of {thread, start, end}
   * for each thread, describing the critical path of the frame.
   */
  function Frame(associatedEvents, threadTimeRanges, opt_args) {
    tr.model.Event.call(this);

    this.threadTimeRanges = threadTimeRanges;
    this.associatedEvents = new tr.model.EventSet(associatedEvents);
    this.args = opt_args || {};

    this.title = 'Frame';
    this.start = Statistics.min(
        threadTimeRanges, function(x) { return x.start; });
    this.end = Statistics.max(
        threadTimeRanges, function(x) { return x.end; });
    this.totalDuration = Statistics.sum(
        threadTimeRanges, function(x) { return x.end - x.start; });

    this.perfClass = FRAME_PERF_CLASS.NEUTRAL;
  }

  Frame.prototype = {
    __proto__: tr.model.Event.prototype,

    set perfClass(perfClass) {
      this.colorId = ColorScheme.getColorIdForReservedName(perfClass);
      this.perfClass_ = perfClass;
    },

    get perfClass() {
      return this.perfClass_;
    },

    shiftTimestampsForward(amount) {
      this.start += amount;
      this.end += amount;

      for (let i = 0; i < this.threadTimeRanges.length; i++) {
        this.threadTimeRanges[i].start += amount;
        this.threadTimeRanges[i].end += amount;
      }
    },

    addBoundsToRange(range) {
      range.addValue(this.start);
      range.addValue(this.end);
    }
  };

  tr.model.EventRegistry.register(
      Frame,
      {
        name: 'frame',
        pluralName: 'frames'
      });

  return {
    Frame,
    FRAME_PERF_CLASS,
  };
});
</script>
